package Offer;

import org.junit.Test;

/**
 * 思路：一个合法的数值，可能存在的两种形式:
 *      A [. [ B ] ] [ E|e C]
 *      . [ B ] [ E|e C]
 *
 *
 *  其中,[]表示可以省略的，同一个[]内的表示必须同时出现
 *  A、C 表示可能 带 '+'、‘-’的数字串
 *  B 表示 不带'+'、‘-’的数字串
 */
public class T20_isNumber {
    private int index=0;  //指向字符串的索引

    //主方法
    public boolean isNumber(String s) {
        if (s == null) {
            return false;
        }

        // 去掉前后的空格
        s = s.trim();

        // 扫描可能存在的整数部分
        boolean numeric = scanInteger(s);

        //存在小数点，则扫描小数部分
        if (index < s.length() && s.charAt(index) == '.') {
            index++;
            // 小数点后面有无数值都是合法的，如 123.11 和 123.
            numeric = scanUnsignedInteger(s) || numeric;
        }

        //如果出现 e|E，则扫描指数部分
        if (index < s.length() && (s.charAt(index) == 'e' || s.charAt(index) == 'E')) {
            index++;
            //e|E 后面必须跟有符号整数,前面也要出现过数值 （e10是不合法的）
            numeric = scanInteger(s) && numeric;
        }

        //如果还没到达字符串末尾，说明存在其他字符，是不合法的
        return numeric && index == s.length();
    }

    //扫描无符号数是否合法
    public boolean scanUnsignedInteger(String s) {
        int flag = index;
        while (index < s.length() && s.charAt(index) >= '0' && s.charAt(index) <= '9') {
            index++;
        }
        //如果index>flag，说明[flag,index)之间存在数字
        return index > flag;
    }


    //扫描有符号整数是否合法（有符号就是多了个判断符号而已）
    public boolean scanInteger(String s) {
        if (index < s.length() && (s.charAt(index) == '+' || s.charAt(index) == '-')) {
            index++;
        }
        return scanUnsignedInteger(s);
    }


    @Test
    public void test() {
//        System.out.println(isNumber("0"));
//        System.out.println(isNumber("e"));
//        System.out.println(isNumber(".1"));
//        System.out.println(isNumber("e10"));
//        System.out.println(isNumber("+++10"));

        System.out.println(isNumber("0.8"));
//        String s = "  a  ";
//        System.out.println(s.trim());
    }
}


// 数值    "+100", "5e2", "-123", "3.1416", "-1E-16", "0123"
// 非数值  "12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"
// e后面必须跟整数
// 最多一个小数点
// 符号后面不能跟符号
// 字符只能是 e|E